<template>
    <ClientOnly>
        <popup
            width="800px"
            :show="visible"
            :title="nextTitle"
            :async-close="true"
            :confirmButtonText="nextStep === 0 ? '下一步' : '上一步'"
            cancelButtonText=""
            @close="emits('close')"
            @confirm="handleNextStep"
        >
            <div class="h-[460px]">
                <el-scrollbar>
                    <template v-if="nextStep === 0">
                        <div v-loading="firstLoading" class="grid gap-x-4 grid-cols-3 p-4">
                            <div
                                v-for="(item, index) in knowsLists"
                                :key="index"
                                class="knowledge"
                                :class="{ active: formData.kb === item.code }"
                                @click="changeKnow(item.code, item.name)"
                            >
                                <photos width="46px" height="46px" radius="6px" :src="item.logo" />
                                <div class="flex-1 ml-2">
                                    <p class="text-base line-clamp-1">{{ item.name }}</p>
                                    <p class="text-xs text-tx-placeholder mt-px">
                                        {{ item.vector_name }}
                                    </p>
                                </div>
                            </div>
                        </div>
                        <el-empty
                            v-if="knowsLists.length <= 0 && !firstLoading"
                            :image-size="120"
                            description="空空如也~"
                        />
                    </template>

                    <template v-else>
                        <div v-loading="firstLoading" class="grid gap-x-4 grid-cols-2 p-4">
                            <div
                                v-for="(item, index) in filesLists"
                                :key="index"
                                class="documents"
                                @click="changeFile(item.code, item.name)"
                            >
                                <photos
                                    width="16px"
                                    height="16px"
                                    radius="6px"
                                    :src="suffixUtil.findUnitIcon(item.name)"
                                />
                                <p class="ml-1.5 line-clamp-1">{{ item.name }}</p>
                            </div>
                        </div>
                        <el-empty
                            v-if="filesLists.length <= 0 && !firstLoading"
                            :image-size="120"
                            description="无可选择文件~"
                        />
                    </template>
                </el-scrollbar>
            </div>
        </popup>

        <popup
            :show="showPop"
            :loading="loading"
            :title="`修正数据【${currKnowName}】(${currFileName})`"
            :async-close="true"
            :footer-border="true"
            width="1000px"
            @close="showPop = false"
            @confirm="handleConfirm"
        >
            <div class="p-3">
                <el-alert type="warning" :closable="false">
                    <template #default>
                        <div class="py-[3px] font-bold">友情提示</div>
                        <div class="py-[3px] ml-4">
                            <p>1、修正数据是: 把当前对话记录重新编辑后，加入到知识库中训练作为数据的补充。</p>
                            <p>2、问: 为什么我修正数据后当前对话记录没有任何变化？而且还能继续修正？</p>
                            <p>3、答: 可以对这条对话记录无限次修正，是对知识库数据的补充，不会变更当前记录。</p>
                        </div>
                    </template>
                </el-alert>
            </div>

            <div class="flex pb-0">
                <div class="flex-1 grid grid-cols-1 gap-4 p-3">
                    <div>
                        <div class="flex items-center gap-1 mb-1">
                            <h3 class="font-bold">问题</h3>
                            <el-tooltip effect="dark" placement="top">
                                <icon name="el-icon-InfoFilled" />
                                <template #content>
                                    该内容会进行向量化训练，内容的质量会影响后续提问的效果。
                                </template>
                            </el-tooltip>
                        </div>

                        <el-input
                            v-model="formData.question"
                            type="textarea"
                            placeholder="主要内容（必填）"
                            resize="none"
                            :rows="15"
                        />
                    </div>
                    <div>
                        <div class="flex items-center gap-1 mb-1">
                            <h3 class="font-bold">答案</h3>
                            <el-tooltip effect="dark" placement="top">
                                <icon name="el-icon-InfoFilled" />
                                <template #content>
                                    <p>该内不会进行向量化，当引用时该内容会拼接上问题一起给到大模型</p>
                                    <p>如果启用问答的模式，该内容将会当作答案进行输出 (不走大模型)。</p>
                                </template>
                            </el-tooltip>
                        </div>
                        <el-input
                            v-model="formData.answer"
                            type="textarea"
                            placeholder="辅助内容 (可选)"
                            resize="none"
                            :rows="15"
                        />
                    </div>
                </div>

                <div class="flex flex-col w-[400px] p-3 border-l border-br-lighter">
                    <div class="flex items-center justify-between mb-2">
                        <h5 class="flex items-center gap-2 font-bold">
                            <span>附件管理 ({{ formData.annex.length }})</span>
                            <el-tooltip effect="dark" placement="top">
                                <icon name="el-icon-InfoFilled" />
                                <template #content>
                                    <p>会根据智能体设置附件相似度来决定答复时是否携带下列附件。</p>
                                    <br />
                                    <p>1. 一条数据最多只能设置10个附件，可以是 [图片、视频、音频、文件]。</p>
                                    <p>2. 务必填写附件的描述信息，最好描述信息与问题内容的意思接近。</p>
                                    <p>3. 如果回复引用到了这条数据，但没有输出这里数据里的图片怎么办?</p>
                                    <p>3-1. 附件的描述与用户提问的问题不匹配，达不到附件相似度。</p>
                                    <p>3-2. 相似度设置过高、智能体 - 知识参数配置】调节相似度。</p>
                                    <p>3-3. 优化附件的描述信息，让其与数据的信息描述意思类似。</p>
                                </template>
                            </el-tooltip>
                        </h5>
                        <el-button
                            type="default"
                            size="small"
                            :icon="Plus"
                            :disabled="formData.annex.length >= 10"
                            @click="handleInsert"
                        >插入</el-button>
                    </div>

                    <el-scrollbar ref="scrollbarRef" height="688px">
                        <Draggable v-model="formData.annex" :item-key="'selected'" animation="300" handle=".drag-move">
                            <template #item="{ element, index }">
                                <div :key="index" class="annex-item">
                                    <upload-single
                                        v-model="element.path"
                                        type="file"
                                        size="70px"
                                        scene=""
                                        folder="agents/know"
                                        tipsText=""
                                        :closeButton="false"
                                        @success="(data: any) => handleUpload(data, index)"
                                    />

                                    <div class="flex-1">
                                        <div class="flex items-center justify-between mb-2">
                                            <div
                                                class="font-bold line-clamp-1"
                                                @click="handleRename(index, element.name)"
                                            >
                                                <span class="text-sm">[{{ index+1 }}]</span>
                                                {{ element.name || '请上传附件' }}
                                            </div>

                                            <div class="flex items-center gap-3 ml-1">
                                                <div class="flex drag-move cursor-move">
                                                    <icon name="el-icon-Rank" />
                                                </div>
                                                <icon
                                                    name="el-icon-Delete"
                                                    class="cursor-pointer hover:text-error mr-1"
                                                    @click="handleDelete(index)"
                                                />
                                            </div>
                                        </div>
                                        <el-input
                                            v-model="element.question"
                                            type="textarea"
                                            placeholder="请输入附件索引描述"
                                            resize="none"
                                            style="height: 38px !important;"
                                            :autosize="{ minRows: 1, maxRows: 50 }"
                                        />
                                    </div>
                                </div>
                            </template>
                        </Draggable>
                    </el-scrollbar>
                </div>
            </div>
        </popup>

    </ClientOnly>
</template>

<script setup lang="ts">
import {Plus} from '@element-plus/icons-vue'
import Draggable from 'vuedraggable'
import suffixUtil from '~/utils/suffix'
import knowManageApi from '~/api/agent/know/manage'
import knowArchiveApi from '~/api/agent/know/archive'
import knowJournalApi from '~/api/agent/robot/journal'

const emits = defineEmits(['confirm', 'close'])
const props = defineProps({
    show: {
        type: Boolean,
        default: false
    },
    bot: {
        type: String,
        default: ''
    },
    question: {
        type: String,
        default: ''
    },
    answer: {
        type: String,
        default: ''
    }
})

const firstLoading = ref<boolean>(true)

const showPop = ref<boolean>(false)
const visible = ref<boolean>(false)
const loading = ref<boolean>(false)
const formData = reactive({
    kb: '',
    fid: '',
    question: '',
    answer: '',
    annex: [] as KnowDatasetAnnexType[]
})

// 步骤下标
const nextStep = ref<number>(0)
// 步骤标题
const nextTitle = ref<string>('选择知识库')
// 知识库列表
const knowsLists = ref<KnowManageWholeResponse[]>([])
// 文件库列表
const filesLists = ref<KnowArchiveWholeResponse[]>([])
// 知识库名称
const currKnowName = ref<string>('')
// 文件库名称
const currFileName = ref<string>('')

/**
 * 选择知识库
 *
 * @param {string} code
 * @param {string} name
 * @author zero
 */
const changeKnow = async (code: string, name: string) => {
    formData.kb = code
    currKnowName.value = name
}

/**
 * 选择文件库
 *
 * @param {string} code
 * @param {string} name
 * @author zero
 */
const changeFile = async (code: string, name: string) => {
    showPop.value = true
    formData.fid = code
    currFileName.value = name
}

/**
 * 处理下一步
 *
 * @author zero
 */
const handleNextStep = async () => {
    if (nextStep.value === 0 && !formData.kb) {
        return feedback.msgError('请选择要保存到那个知识库')
    }

    firstLoading.value = true
    if (nextStep.value === 0) {
        nextStep.value = 1
        nextTitle.value = `选择文件 (${currKnowName.value})`
        filesLists.value = await knowArchiveApi.whole(formData.kb)
    } else {
        nextStep.value = 0
        nextTitle.value = '选择知识库'
    }
    firstLoading.value = false
}

/**
 * 处理确认修正
 */
const handleConfirm = async () => {
    if (formData.annex.length > 10) {
        return feedback.msgError('附件不能超出10个')
    }

    const types = ['image', 'video', 'audio', 'file']
    for (let index = 0; index < formData.annex.length; index++) {
        const element = formData.annex[index]
        formData.annex[index].sort = index
        if (!element.type || !element.path) {
            const i = index + 1
            return feedback.msgError('请上传附件文件【' + i + '】')
        }
        if (!types.includes(element.type)) {
            formData.annex[index].type = 'file'
        }
    }

    loading.value = true
    await knowJournalApi.corrects({
        bot: props.bot,
        kb: formData.kb,
        fid: formData.fid,
        question: formData.question,
        answer: formData.answer,
        annex: formData.annex
    }).finally(() => {
        loading.value = false
    })

    visible.value = false
    showPop.value = false
    feedback.msgSuccess('修正成功')
    emits('close')
}

/**
 * 附件插入
 *
 * @author zero
 */
const handleInsert = () => {
    if (formData.annex.length >= 10) {
        return feedback.msgError('附件不能超出10个')
    }
    formData.annex.push({
        type: '',
        name: '',
        path: '',
        size: 0,
        ext: '',
        sort: 0,
        question: ''
    })
}

/**
 * 附件删除
 *
 * @param {number} index
 * @author zero
 */
const handleDelete = (index: number) => {
    formData.annex.splice(index, 1)
}

/**
 * 附件上传
 *
 * @param {any} data
 * @param {number} index
 * @author zero
 */
const handleUpload = (data: any, index: number) => {
    formData.annex[index].type = data.type
    formData.annex[index].name = data.name
    formData.annex[index].size = data.size
    formData.annex[index].path = data.url
    formData.annex[index].ext = data.ext
}

/**
 * 附件命名
 *
 * @param {number} index
 * @param {string} filename
 * @author zero
 */
const handleRename = (index: number, filename: string) => {
    if (!filename) {
        return feedback.msgError('请先上传附件')
    }

    const arr: string[] = filename.split('.')
    const ext: string = arr.pop() || ''
    const val: string = arr.join('.')

    feedback.prompt('请输入新的名称', '文件重命名', {
        inputType: 'textarea',
        inputValue: val,
        inputPattern: /.+/,
        inputErrorMessage: '文件名称不能为空',
    }).then(async (v) => {
        formData.annex[index].name = v.value + '.' + ext
    }).catch(() => {})
}

watch(
    () => props.show,
    async (val) => {
        visible.value = val
        if (val) {
            nextStep.value = 0
            formData.question = props.question
            formData.answer = props.answer
            knowsLists.value = await knowManageApi.whole(props.bot)
            firstLoading.value = false
        }
    }, { immediate: true }
)
</script>

<style scoped lang="scss">
.knowledge {
    display: flex;
    align-items: center;
    padding: 10px;
    margin-bottom: 10px;
    cursor: pointer;
    border: 1px solid var(--el-border-color-light);
    border-radius: 8px;
    &:hover {
        cursor: pointer;
        background-color: var(--el-bg-color-page);
        box-shadow: var(--el-box-shadow-light);
    }
    &.active {
        cursor: default;
        background-color: var(--el-color-primary-light-9);
        border-color: var(--el-color-primary-light-5);
    }
}

.documents {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 14px;
    margin-bottom: 12px;
    cursor: pointer;
    border: 1px solid var(--el-border-color-light);
    border-radius: 8px;
    &:hover {
        cursor: pointer;
        background-color: var(--el-bg-color-page);
        box-shadow: var(--el-box-shadow-light);
    }
    &.active {
        background-color: var(--el-color-primary-light-9);
        border-color: var(--el-color-primary);
    }
    h3 {
        margin: 0 4px;
        font-size: 14px;
        color: var(--el-text-color-regular);
    }
}

.annex-item {
    display: flex;
    gap: 8px;
    padding: 6px;
    margin-bottom: 10px;
    background-color: var(--el-bg-color-lighter);
    border: 1px solid var(--el-border-color-light);
    border-radius: 6px;
    :deep(.el-textarea__inner) {
        height: 36px !important;
        min-height: 36px !important;
        padding: 3px 2px;
        font-size: 13px;
        color: var(--el-text-color-secondary);
        background-color: transparent;
        box-shadow: none;
        &:focus,
        &:hover {
            box-shadow: 0 0 0 1px var(--el-color-primary, var(--el-color-primary))
        }
        &:focus {
            padding: 3px 8px;
            background-color: var(--el-bg-color);
        }
    }
}
</style>
